package org.xwalk.core.internal;

import android.util.Log;
import java.io.InputStream;
import java.io.StringBufferInputStream;
import java.util.Map;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

public class XWalkWebResourceResponseBridge extends XWalkWebResourceResponseInternal {
    private XWalkCoreBridge coreBridge;
    private Object wrapper;

    public Object getWrapper() {
        return wrapper;
    }


    private XWalkWebResourceResponseInternal internal;

    XWalkWebResourceResponseBridge(XWalkWebResourceResponseInternal internal) {
        this.internal = internal;
        reflectionInit();
    }

    @Override
    public void setMimeType(String mimeType) {
        if (setMimeTypeStringMethod == null || setMimeTypeStringMethod.isNull()) {
            setMimeTypeSuper(mimeType);
        } else {
            setMimeTypeStringMethod.invoke(mimeType);
        }
    }

    public void setMimeTypeSuper(String mimeType) {
        if (internal == null) {
            super.setMimeType(mimeType);
        } else {
            internal.setMimeType(mimeType);
        }
    }

    private ReflectMethod setMimeTypeStringMethod = new ReflectMethod(null, "setMimeType");

    @Override
    public String getMimeType() {
        if (getMimeTypeMethod == null || getMimeTypeMethod.isNull()) {
            return getMimeTypeSuper();
        } else {
            return (String)getMimeTypeMethod.invoke();
        }
    }

    public String getMimeTypeSuper() {
        String ret;
        if (internal == null) {
            ret = super.getMimeType();
        } else {
            ret = internal.getMimeType();
        }
        if (ret == null) return null;
        return ret;
    }

    private ReflectMethod getMimeTypeMethod = new ReflectMethod(null, "getMimeType");

    @Override
    public void setEncoding(String encoding) {
        if (setEncodingStringMethod == null || setEncodingStringMethod.isNull()) {
            setEncodingSuper(encoding);
        } else {
            setEncodingStringMethod.invoke(encoding);
        }
    }

    public void setEncodingSuper(String encoding) {
        if (internal == null) {
            super.setEncoding(encoding);
        } else {
            internal.setEncoding(encoding);
        }
    }

    private ReflectMethod setEncodingStringMethod = new ReflectMethod(null, "setEncoding");

    @Override
    public String getEncoding() {
        if (getEncodingMethod == null || getEncodingMethod.isNull()) {
            return getEncodingSuper();
        } else {
            return (String)getEncodingMethod.invoke();
        }
    }

    public String getEncodingSuper() {
        String ret;
        if (internal == null) {
            ret = super.getEncoding();
        } else {
            ret = internal.getEncoding();
        }
        if (ret == null) return null;
        return ret;
    }

    private ReflectMethod getEncodingMethod = new ReflectMethod(null, "getEncoding");

    @Override
    public void setData(InputStream data) {
        if (setDataInputStreamMethod == null || setDataInputStreamMethod.isNull()) {
            setDataSuper(data);
        } else {
            setDataInputStreamMethod.invoke(data);
        }
    }

    public void setDataSuper(InputStream data) {
        if (internal == null) {
            super.setData(data);
        } else {
            internal.setData(data);
        }
    }

    private ReflectMethod setDataInputStreamMethod = new ReflectMethod(null, "setData");

    @Override
    public InputStream getData() {
        if (getDataMethod == null || getDataMethod.isNull()) {
            return getDataSuper();
        } else {
            return (InputStream)getDataMethod.invoke();
        }
    }

    public InputStream getDataSuper() {
        InputStream ret;
        if (internal == null) {
            ret = super.getData();
        } else {
            ret = internal.getData();
        }
        if (ret == null) return null;
        return ret;
    }

    private ReflectMethod getDataMethod = new ReflectMethod(null, "getData");

    @Override
    public void setStatusCodeAndReasonPhrase(int statusCode, String reasonPhrase) {
        if (setStatusCodeAndReasonPhraseintStringMethod == null || setStatusCodeAndReasonPhraseintStringMethod.isNull()) {
            setStatusCodeAndReasonPhraseSuper(statusCode, reasonPhrase);
        } else {
            setStatusCodeAndReasonPhraseintStringMethod.invoke(statusCode, reasonPhrase);
        }
    }

    public void setStatusCodeAndReasonPhraseSuper(int statusCode, String reasonPhrase) {
        if (internal == null) {
            super.setStatusCodeAndReasonPhrase(statusCode, reasonPhrase);
        } else {
            internal.setStatusCodeAndReasonPhrase(statusCode, reasonPhrase);
        }
    }

    private ReflectMethod setStatusCodeAndReasonPhraseintStringMethod = new ReflectMethod(null, "setStatusCodeAndReasonPhrase");

    @Override
    public int getStatusCode() {
        if (getStatusCodeMethod == null || getStatusCodeMethod.isNull()) {
            return getStatusCodeSuper();
        } else {
            return (Integer)getStatusCodeMethod.invoke();
        }
    }

    public int getStatusCodeSuper() {
        int ret;
        if (internal == null) {
            ret = super.getStatusCode();
        } else {
            ret = internal.getStatusCode();
        }
        
        return ret;
    }

    private ReflectMethod getStatusCodeMethod = new ReflectMethod(null, "getStatusCode");

    @Override
    public String getReasonPhrase() {
        if (getReasonPhraseMethod == null || getReasonPhraseMethod.isNull()) {
            return getReasonPhraseSuper();
        } else {
            return (String)getReasonPhraseMethod.invoke();
        }
    }

    public String getReasonPhraseSuper() {
        String ret;
        if (internal == null) {
            ret = super.getReasonPhrase();
        } else {
            ret = internal.getReasonPhrase();
        }
        if (ret == null) return null;
        return ret;
    }

    private ReflectMethod getReasonPhraseMethod = new ReflectMethod(null, "getReasonPhrase");

    @Override
    public void setResponseHeaders(Map<String, String> headers) {
        if (setResponseHeadersMapMethod == null || setResponseHeadersMapMethod.isNull()) {
            setResponseHeadersSuper(headers);
        } else {
            setResponseHeadersMapMethod.invoke(headers);
        }
    }

    public void setResponseHeadersSuper(Map<String, String> headers) {
        if (internal == null) {
            super.setResponseHeaders(headers);
        } else {
            internal.setResponseHeaders(headers);
        }
    }

    private ReflectMethod setResponseHeadersMapMethod = new ReflectMethod(null, "setResponseHeaders");

    @Override
    public Map<String, String> getResponseHeaders() {
        if (getResponseHeadersMethod == null || getResponseHeadersMethod.isNull()) {
            return getResponseHeadersSuper();
        } else {
            return (Map<String, String>)getResponseHeadersMethod.invoke();
        }
    }

    public Map<String, String> getResponseHeadersSuper() {
        Map<String, String> ret;
        if (internal == null) {
            ret = super.getResponseHeaders();
        } else {
            ret = internal.getResponseHeaders();
        }
        if (ret == null) return null;
        return ret;
    }

    private ReflectMethod getResponseHeadersMethod = new ReflectMethod(null, "getResponseHeaders");


    void reflectionInit() {
        coreBridge = XWalkCoreBridge.getInstance();
        if (coreBridge == null) return;

        ReflectConstructor constructor = new ReflectConstructor(
                coreBridge.getWrapperClass("XWalkWebResourceResponse"), Object.class);
        try {
            wrapper = constructor.newInstance(this);
        } catch (UnsupportedOperationException e) {
            return;
        }

        setMimeTypeStringMethod.init(wrapper, null,
                "setMimeType", String.class);
        getMimeTypeMethod.init(wrapper, null,
                "getMimeType");
        setEncodingStringMethod.init(wrapper, null,
                "setEncoding", String.class);
        getEncodingMethod.init(wrapper, null,
                "getEncoding");
        setDataInputStreamMethod.init(wrapper, null,
                "setData", InputStream.class);
        getDataMethod.init(wrapper, null,
                "getData");
        setStatusCodeAndReasonPhraseintStringMethod.init(wrapper, null,
                "setStatusCodeAndReasonPhrase", int.class, String.class);
        getStatusCodeMethod.init(wrapper, null,
                "getStatusCode");
        getReasonPhraseMethod.init(wrapper, null,
                "getReasonPhrase");
        setResponseHeadersMapMethod.init(wrapper, null,
                "setResponseHeaders", Map.class);
        getResponseHeadersMethod.init(wrapper, null,
                "getResponseHeaders");
    }
}
